package service

import (
	"context"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/spf13/cast"
	"hash/fnv"
	"log"
	"math/rand"
	"nearby/biz/common"
	"time"

	"mime/multipart"
	"nearby/biz/manager/ali_oss"
	"nearby/biz/model"
	"path/filepath"
)

type UploadImageService struct {
}

func (ss *UploadImageService) checkParam(file *multipart.FileHeader) error {
	// 校验图片类型
	if !ali_oss.IsImage(file.Filename) {
		return errors.New("未知的图片类型")
	}
	// 校验图片大小
	// todo 等着可以做压缩
	if file.Size > common.ImageSizeLimit {
		return errors.New("请上传5MB以内的文件")
	}
	return nil
}

func (ss *UploadImageService) Execute(c *gin.Context, req *model.UploadImageRequest) (*model.UploadImageResponse, error) {
	file, err := c.FormFile("file")
	if err != nil {
		log.Printf("ctx: %+v; c.MultipartForm() fail, err: %+v", c, err)
		return nil, common.NewBizErr(common.BizErrCode, fmt.Sprintf("解析文件的时候有问题, 报错: c.MultipartForm(), err: %+v", err), err)
	}
	if err = ss.checkParam(file); err != nil {
		return nil, common.NewBizErr(common.BizErrCode, err.Error(), err)
	}
	key := ss.GenerateObjKey(c, file.Filename)
	if err = ss.UploadImage(c, key, file); err != nil {
		return nil, common.NewBizErr(common.BizErrCode, err.Error(), err)
	}

	return &model.UploadImageResponse{
		Meta:     common.MetaOk,
		ImageURL: ali_oss.GetUrl(key),
	}, nil
}

func (ss *UploadImageService) UploadImage(ctx context.Context, key string, file *multipart.FileHeader) error {
	fileHandle, err := file.Open() //打开上传文件
	if err != nil {
		return err
	}
	defer fileHandle.Close()
	return ali_oss.UploadFile(ctx, key, fileHandle)
}

func hash(s string) uint32 {
	h := fnv.New32a()
	h.Write([]byte(s))
	return h.Sum32()
}

func (ss *UploadImageService) GenerateObjKey(ctx context.Context, filename string) string {
	ext := filepath.Ext(filename)
	user := common.GetUser(ctx)
	dir := fmt.Sprintf("images/%s", time.Now().Format("200601"))
	u := hash(cast.ToString(user.UserID))
	t := time.Now().Unix()
	r := rand.Intn(100)
	return fmt.Sprintf("%s/%d_%d_%d%s", dir, u, t, r, ext)
}
